/***********************************************************************************************//**
*\n  @file       device_uart.cpp
*\n  @brief      RS232/RS485设备类
*\n  @details
*\n -----------------------------------------------------------------------------------
*\n  文件说明：
*\n       1. RS232/RS485设备类
*\n
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01   罗先能        2021.5.12          创建
*\n
***************************************************************************************************/

/**************************************************************************************************
* 头文件
***************************************************************************************************/
#include <iostream>
#include <termios.h>
#include "bus_spi.hpp"
#include "device_gpio.hpp"
#include "device_uart.hpp"

#undef  DEBUG_LEVEL
#define DEBUG_LEVEL  2   // 定义debug级别 (0 ~ 5)
#include "vdebug.h"

using namespace std;

/**************************************************************************************************
* 宏定义、结构定义
***************************************************************************************************/
#ifdef  __cplusplus //-- C only -----------------------------------------------------------
extern "C" {
#endif


#ifdef  __cplusplus //--C end -------------------------------------------------------------
}
#endif

/**************************************************************************************************
* 全局变量声明、定义
***************************************************************************************************/

#if 1
/**************************************************************************************************
* 私有变量声明、定义
***************************************************************************************************/
// 静态成员变量初始化:
TRs232FromSpi *TRs232FromSpi::tSelf[2] = { NULL, NULL };
TBus*          TRs232FromSpi::pIfSpi   = NULL;
TDevice*       TRs232FromSpi::pIfGpio  = NULL;
pthread_t      TRs232FromSpi::iTid     = -1;
pthread_t      TRs232FromSpi::iTxTid   = -1;
int            TRs232FromSpi::gpioFd   = -1;
int            TRs232FromSpi::iReference = 0;
sem_t          TRs232FromSpi::semTx;

/**************************************************************************************************
* 私有函数声明、定义
***************************************************************************************************/


/*************************************************************************************//**
*\n 函数名称： TRs232FromSpi.GpioInterruptTask()
*\n 功能描述：
*\n            接收线程: GPIO中断处理线程(静态函数)
*\n 输入参数：
*\n            void *arg
*\n 输出参数:
*\n
*\n 返 回 值:
*\n           无
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2021.6.29     创建
*****************************************************************************************/
void* TRs232FromSpi::GpioInterruptTask(void *arg)
{
    while (1)
    {
    	// 等待gpio中断（spi2uart芯片的中断信号）
        int ret = pIfGpio->Read(null, NULL, null);
        if (ret <= 0)
        {
	        debug_printf("pIfGpio->Read() < 0\n");
            continue;
        }

        /*
        // 读取spi2uart的中断状态值IIR(并清除中断标志);
        //   通道0:   Bit[0 ~15];
        //   通道1: Bit[16~31];
        //   一下为中断状态值说明
		//   IIR[5:0],  Priority level, Interrupt type,       Interrupt source
		//   000001,    none,           none,                 none;
		//   000110,    1,              receiver line status, Overrun Error (OE), Framing Error (FE), Parity Error(PE),
		//		                                           or Break Interrupt (BI) errors occur in characters in the RX FIFO
		//   001100,    2,              RX time-out,          stale data in RX FIFO;
		//   000100,    2,              RHR interrupt,        receive data ready (FIFO disable) or
		//		                                           RX FIFO above trigger level (FIFO enable)
		//   000010,    3,              THR interrupt,        transmit FIFO empty (FIFO disable) or
		//		                                           TX FIFO passes above trigger level (FIFO enable)
		//   000000,    4,              modem status,         change of state of modem input pins
		//	 001110,    5,              I/O pins,             input pins change of state
		//	 010000,    6,              Xoff interrupt,       receive Xoff character(s)/special character
		//   100000,    7,              CTS/RTS,              RTS pin or CTS pin change state from active (LOW) to inactive (HIGH)
		*/
        u32 status;
        ret = TRs232FromSpi::pIfSpi->Ioctl(GET_STATUS, &status);
        if (ret < 0)
        {
            debug_printf("pIfSpi->Ioctl(GET_STATUS) < 0\n");
            continue;
        }
		if ((status & 0x00040004) == 0)
		{
			debug_printf("status == 0x%08x \n", status);
			continue;
		}
		debug_info("status == 0x%08x \n", status);

        // 接收通道0接收中断状态;
        if (status & 0x0004)
        {
        	int channel = 0;
            if(tSelf[channel] != NULL)
            {
            	TRs232FromSpi *self = tSelf[channel];
            	self->IrqRead(channel);
            }
			debug_info("recv channe[0]\n");
        }

		// 接收通道1中断状态;
        if ((status >> 16) & 0x0004)
        {
        	int channel = 1;
            if(tSelf[channel] != NULL)
            {
            	TRs232FromSpi *self = tSelf[channel];
            	self->IrqRead(channel);
            }
			debug_info("recv channe[1]\n");
        }
    }

    pthread_exit(NULL);
}


/*************************************************************************************//**
*\n 函数名称： TRs232FromSpi.TxInterruptTask()
*\n 功能描述：
*\n           TX发送线程, 将txBuffer中的数据分包（每包小于64bytes）发送
*\n 输入参数：
*\n           void *arg
*\n 输出参数:
*\n
*\n 返 回 值:
*\n           无
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2021.6.29     创建
*****************************************************************************************/
void* TRs232FromSpi::TxInterruptTask(void *arg)
{
	int ret;
	int iEnableSend;
	int iEnableSend1;

	TRs232FromSpi *self  = tSelf[0];
	TRs232FromSpi *self1 = tSelf[1];

    while (1)
    {
	loop1:
		// 等待发送通知
		sem_wait(&TRs232FromSpi::semTx);

		while(1)
		{
		loop2:
			iEnableSend = iEnableSend1 = 0;
			if (self  != NULL)	iEnableSend  = self->iEnableSend;
			if (self1 != NULL)	iEnableSend1 = self1->iEnableSend;
			if ((iEnableSend == 0) && (iEnableSend1 == 0))
			{
				debug_printf("goto loop1\n");
				goto loop1;
			}
			/***********************
			// 读取spi2uart芯片中剩余txfifo长度;
			u32 txFifoLength;
			txFifoLength == 0;
			ret = TRs232FromSpi::pIfSpi->Ioctl(GET_TXFIFO, &txFifoLength);
			if ((ret < 0) || (txFifoLength == 0))
			{
				debug_printf("txFifoLength == 0\n");
				usleep(10*1000);
				continue;
			}
			debug_info("txFifoLength == 0x%08x \n", txFifoLength);

			if (iEnableSend > 0)
			{
				int iSize = self->mTxFifoSize;
			}
			**************************/

			// 通道0数据接力发送;
			if (iEnableSend > 0)
			{
				long iSize = self->mTxFifoSize;
				iSize = iSize < 64 ? iSize : 64;
				ret = self->IrqWrite(self->mpTxFifoTop, iSize);
				if (ret > 0)
				{
					self->Lock();
					self->mpTxFifoTop += ret;  // 下次数据的起始地址
					self->mTxFifoSize -= ret;  // 剩余数据长度
					self->Unlock();
				}
				if (self->mTxFifoSize <= 0)
				{
					iEnableSend = 0;
					self->iEnableSend = 0;
				}
				debug_printf("send[%d], remain=%d, flag=%d\n", ret, self->mTxFifoSize, iEnableSend);
			}

			// 通道1数据接力发送;
			if (iEnableSend1 > 0)
			{
				long iSize = self1->mTxFifoSize;
				iSize = iSize < 64 ? iSize : 64;
				ret = self1->IrqWrite(self1->mpTxFifoTop, iSize);
				if (ret > 0)
				{
					self1->Lock();
					self1->mpTxFifoTop += ret;  // 下次数据的起始地址
					self1->mTxFifoSize -= ret;  // 剩余数据长度
					self1->Unlock();
				}
				if (self1->mTxFifoSize <= 0)
				{
					iEnableSend1 = 0;
					self1->iEnableSend = 0;
				}
				debug_printf("send1[%d], remain=%d, flag=%d\n", ret, self1->mTxFifoSize, iEnableSend1);
			}

			if ((iEnableSend > 0)  || (iEnableSend1 > 0))
			{
				// debug_printf("usleep()\n");
				usleep(5*1000);
			}
		}
    }

    pthread_exit(NULL);
}


/**************************************************************************************************
* 全局函数声明、定义
***************************************************************************************************/
// 构造函数
TRs232FromSpi::TRs232FromSpi(const char *name, TDevice *pGpio, TBus *pSpi, u32 index)
{
    this->iReference++;
    if(index >= 2)
    {
        debug_error("%s->index == %d\n", name, index);
        return;
    }

    // 1. 保存名称
	memset(this->mName, 0, sizeof(this->mName));
	int iSize = sizeof(this->mName) - 1;
	iSize = iSize < strlen(name)  ? iSize : strlen(name);
	memcpy(this->mName, name, iSize);

	sem_init(&this->semRx, 0, 0);

    this->pBus = pSpi;  // spi总线

    // {{{  静态参数(只需要1次)
	TRs232FromSpi::tSelf[index] =  this;
    if(NULL == TRs232FromSpi::pIfSpi)
        TRs232FromSpi::pIfSpi = pSpi;      // spi实例
    if(NULL == TRs232FromSpi::pIfGpio)
    	TRs232FromSpi::pIfGpio = pGpio;    // gpio实例

	// 创建gpio口的监控线程（只创建1次）
	if(-1 == TRs232FromSpi::iTid)
	{
		// 设置线程优先级
		static pthread_attr_t attr;
		pthread_attr_init(&attr);
		pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
		pthread_attr_setschedpolicy(&attr, SCHED_RR);
		static struct sched_param param;
		param.sched_priority = 60;
		pthread_attr_setschedparam(&attr, &param);
		// 中断处理线程
		int ret = pthread_create(&TRs232FromSpi::iTid, &attr,
                                  TRs232FromSpi::GpioInterruptTask, NULL);
		if(0 != ret)
		{
			TRs232FromSpi::iTid = -1;
			debug_error("pthread_create() < 0,%s\n", strerror(errno));
			//return;
		}
	}
	// 创建tx发送线程（只创建1次）
	if(-1 == TRs232FromSpi::iTxTid)
	{
		// 设置线程优先级
		static pthread_attr_t attr;
		pthread_attr_init(&attr);
		pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
		pthread_attr_setschedpolicy(&attr, SCHED_RR);
		static struct sched_param param;
		param.sched_priority = 60;
		pthread_attr_setschedparam(&attr, &param);
		// 中断处理线程
		int ret = pthread_create(&TRs232FromSpi::iTxTid, &attr,
                                  TRs232FromSpi::TxInterruptTask, NULL);
		if(0 != ret)
		{
			TRs232FromSpi::iTid = -1;
			debug_error("pthread_create() < 0,%s\n", strerror(errno));
			//return;
		}
		sem_init(&TRs232FromSpi::semTx, 0, 0);
	}
    // }}}

	// rx:
    this->mFd = -1;
    mpFifoTop = mpFifoBottom = mFifoBuffer;
    mFifoIndex = mFifoSize = 0;
	// tx:
    mpTxFifoTop  = mTxFifoBuffer;
    mTxFifoSize = 0;
	iEnableSend  = 0;
}

// 析构函数
TRs232FromSpi::~TRs232FromSpi()
{
    // 处理静态函数等
    this->iReference--;
    if (( this->iReference <= 0) && (-1 != TRs232FromSpi::iTid))
    {
        pthread_cancel(TRs232FromSpi::iTid);
        TRs232FromSpi::iTid = -1;
        // 关闭gpio
        pIfGpio->Close(NULL);
    }

}

// virtual
int TRs232FromSpi::Open(void *pHandle)
{
    if((NULL == pHandle) || (NULL == this->pBus) || (NULL == pIfGpio))
    {
        if(NULL == pHandle)
            debug_error("NULL == pHandle \n");
        else if(NULL == pBus)
            debug_error("NULL == pHandle \n");
        else if(NULL == pIfGpio)
            debug_error("NULL == pGpioDevice \n");

        return -1;
    }

    int ret;
    TRs232Handle *tHandle1 = (TRs232Handle *)pHandle;
    // 设置波特率(初始化了全部寄存器,需要最先设置)
    ret = pBus->Ioctl(SET_BPS, (void*)tHandle1->iBandrate);
    if (ret < 0)
    {
        debug_error("Ioctl(SET_BPS) < 0\n");
        return -1;
    }
    // 设置停止位
    ret = pBus->Ioctl(SET_STOP_BIT, (void*)tHandle1->iStopBit);
    if (ret < 0)
    {
        debug_error("Ioctl(SET_STOP_BIT) < 0\n");
        return -1;
    }
    // 设置奇偶校验位
	ret = pBus->Ioctl(SET_PARITY, (void*)tHandle1->iParity);
	if (ret < 0)
	{
		// debug_error("Ioctl(SET_PARITY) < 0\n");
		// return -1;
	}
	ret = pBus->Ioctl(SET_DATABITS, (void*)tHandle1->iDataBits);
	if (ret < 0)
	{
		// debug_error("Ioctl(SET_PARITY) < 0\n");
		// return -1;
	}

    // 开启gpio
    if(TRs232FromSpi::gpioFd == -1)
    {
        TRs232FromSpi::gpioFd = pIfGpio->Open(NULL);
        if (TRs232FromSpi::gpioFd < 0)
        {
            debug_error("pIfGpio->Open() < 0\n");
            return -1;
        }
    }

	this->Lock();
	this->mFifoMode = tHandle1->iFifoMode;
	this->mRxSize = this->mFifoSize = 0;
	this->mFifoIndex = 0;
	this->mFd = 1;
	this->Unlock();
    return  0;
}

// virtual
int TRs232FromSpi::Close(void *pHandle)
{
    // TRs232Handle *tHandle1 = (TRs232Handle *)pHandle;
	this->Lock();
	this->mRxSize = this->mFifoSize = 0;
	this->mFifoIndex = 0;
	this->mFd = -1;
	this->Unlock();
	sem_post(&(this->semRx));
    return 0;
}

// 中断中调用,读取spi2uart芯片中的FIFO数据;
void TRs232FromSpi::IrqRead(int channel)
{
    mRxSize = pBus->Read(0, mRxIrqBuffer, sizeof(mRxIrqBuffer));  // spi接口
    if (mRxSize <= 0)
    {
    	debug_printf("pBus->Read() == %d\n", mRxSize);
    	return;
	}
	if (this->mFd < 0)
	{ // not open()!
		return;
	}

	// 增加Fifo缓存接收数据;
	if (mFifoMode == 0) // fifo满则停止
	{
		this->Lock();
		for (int i = 0; i < mRxSize; i++)
		{
			// FIFO is Full ?
			if (mFifoSize >= MAX_SIZE_FIFO)
				break;
			mFifoBuffer[mFifoIndex++] = mRxIrqBuffer[i];
			mFifoIndex %= MAX_SIZE_FIFO;
			mFifoSize++;
		}
		mpFifoTop    = mFifoBuffer + mFifoIndex;              // top_ptr;
		mpFifoBottom = mFifoBuffer + mFifoIndex - mFifoSize;  // bottom_ptr
		mpFifoBottom =  (mpFifoBottom < mFifoBuffer) ? (mpFifoBottom+MAX_SIZE_FIFO) : mpFifoBottom;
		this->Unlock();

		debug_printf("fifo0: read %d bytes\n", mRxSize);
	}
	else   // fifo满覆盖
	{
		this->Lock();
		for (int i = 0; i < mRxSize; i++)
		{
			mFifoBuffer[mFifoIndex++] = mRxIrqBuffer[i];
			mFifoIndex %= MAX_SIZE_FIFO;
			mFifoSize++;
		}
		mFifoSize = (mFifoSize < MAX_SIZE_FIFO) ? mFifoSize : MAX_SIZE_FIFO;
		mpFifoTop    = mFifoBuffer + mFifoIndex;              // top_ptr;
		mpFifoBottom = mFifoBuffer + mFifoIndex - mFifoSize;  // bottom_ptr
		mpFifoBottom =  (mpFifoBottom < mFifoBuffer) ? (mpFifoBottom+MAX_SIZE_FIFO) : mpFifoBottom;
		this->Unlock();

		debug_printf("fifo1: read %d bytes\n", mRxSize);
	}

	sem_post(&(this->semRx));
}

// virtual
int TRs232FromSpi::Read(long address, void *pBuf, long iSizeToRead)
{
    // 等待gpio中断, 并通过spi读取数据
    if ((mFd < 0) || (iSizeToRead <= 0))
    	return -1;


	//sem_wait(&(this->sem)); /*   阻塞方式 */
	if (mFifoSize <= 0)       /* 非阻塞方式 */
	{
		debug_printf("mFifoSize <= 0\n");
    	return 0;
	}


	this->Lock();
    long ret = iSizeToRead < mFifoSize ? iSizeToRead : mFifoSize;
	if ((mpFifoBottom + ret) < (mFifoBuffer + MAX_SIZE_FIFO))
	{
		// fifo 数据连续
    	memcpy((char*)pBuf, mpFifoBottom, ret);
		this->mFifoSize -= ret;
		mpFifoBottom = mpFifoBottom + ret;
		mpFifoBottom = (mpFifoBottom < (mFifoBuffer + MAX_SIZE_FIFO)) ?
                        mpFifoBottom : (mpFifoBottom - MAX_SIZE_FIFO);
	}
	else
	{
		// fifo数据不连续
		long tmpSize = (mFifoBuffer + MAX_SIZE_FIFO) - mpFifoBottom;
    	memcpy((char*)pBuf, mpFifoBottom, tmpSize);
    	memcpy((char*)pBuf+tmpSize, mFifoBuffer, ret - tmpSize);
		this->mFifoSize -= ret;
		mpFifoBottom = mpFifoBottom + ret;
		mpFifoBottom = (mpFifoBottom < (mFifoBuffer + MAX_SIZE_FIFO)) ?
                	    mpFifoBottom : (mpFifoBottom - MAX_SIZE_FIFO);
	}
	this->Unlock();
    return ret;
}




// tx发送线程中调用, 多次发送fifo buffer中的数据
int TRs232FromSpi::IrqWrite(void *pBuf, long iSizeToWrite)
{
    int ret = pBus->Write(0, pBuf, iSizeToWrite);
    return ret;
}

// virtual
/*************************************************************************************//**
*\n 函数名称： TRs232FromSpi.Write()
*\n 功能描述：
*\n            发送数据
*\n 输入参数：
*\n            long address      ：忽略
*\n            void *pBuf        ：数据
*\n            long iSizeToWrite : 长度 (小于MAX_SIZE_FIFO)
*\n 输出参数:
*\n
*\n 返 回 值:
*\n           n 成功发送的数据长度bytes; -1 失败; -n    错误码
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2021.6.25     创建
*****************************************************************************************/
int TRs232FromSpi::Write(long address, void *pBuf, long iSizeToWrite)
{
    if(mFd < 0)
    	return -1;

	if (this->mTxFifoSize > 0)
	{
		// 上次发送帧还未完成，需要等待；
		debug_error("txFifoBuffer[] is not Empty\n");
		return -ENOMEM;
	}

	this->Lock();
	mTxFifoSize = iSizeToWrite < MAX_SIZE_FIFO-1 ? iSizeToWrite : MAX_SIZE_FIFO-1;
	memcpy(mTxFifoBuffer, pBuf, mTxFifoSize);
	mpTxFifoTop  = mTxFifoBuffer;
	this->iEnableSend = 1;  // 发送控制开关
	this->Unlock();

	// 通知接收线程发送数据
	sem_post(&(TRs232FromSpi::semTx));
	debug_printf("pBuf[%d]=%s\n", iSizeToWrite, pBuf);
	return (int)mTxFifoSize;
}

// public:
int TRs232FromSpi::Ioctl(long cmd, void *pBuf, long *pSize)  //override
{
	if(NULL == this->pBus)
	{
		debug_error("pBus == NULL \n");
		return -1;
	}

	int ret = -1;
	switch (cmd)
	{
	case CMD_CLEAN_RX_BUFFER:		// 清除RX buffer数据
		this->Lock();
    	mFifoIndex = mFifoSize = 0;
		mpFifoTop = mpFifoBottom = mFifoBuffer;
		this->Unlock();
		ret = 0;
		break;
	}

	return(ret);
}

#endif


#if 1
TRs232::TRs232(const char *name, const char *pDevicePath)
{
    // 1. 保存名称
	memset(mName, 0, sizeof(mName));
	int iSize = sizeof(mName) - 1;
	iSize = iSize < strlen(name)  ? iSize : strlen(name);
	memcpy(this->mName, name, iSize);

	this->mpPath = pDevicePath;
	this->mFd = -1;
}

//virtual
TRs232::~TRs232()
{
	if(this->mFd != -1)
	{
		close(mFd);
		this->mFd = -1;
	}
}

// 波特率(单位 bps)
int TRs232::SetBandrate(int iBandrate)
{
//	static int speed_arr[] =
//	{ B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B600, B300, };

	//获取当前的串口配置
	int ret;
	struct termios termOptions;
	ret = tcgetattr(mFd, &termOptions);
	if(ret != 0)
	{
		debug_error("tcgetattr()\n");
		return -1;
	}

	switch(iBandrate)
	{
	default:
	case 115200:
		cfsetispeed(&termOptions, B115200);
		cfsetospeed(&termOptions, B115200);
		break;

	case 57600:
		cfsetispeed(&termOptions, B57600);
		cfsetospeed(&termOptions, B57600);
		break;

	case 38400:
		cfsetispeed(&termOptions, B38400);
		cfsetospeed(&termOptions, B38400);
		break;

	case 19200:
		cfsetispeed(&termOptions, B19200);
		cfsetospeed(&termOptions, B19200);
		break;

	case 9600:
		cfsetispeed(&termOptions, B9600);
		cfsetospeed(&termOptions, B9600);
		break;

	case 4800:
		cfsetispeed(&termOptions, B4800);
		cfsetospeed(&termOptions, B4800);
		break;

	case 2400:
		cfsetispeed(&termOptions, B2400);
		cfsetospeed(&termOptions, B2400);
		break;

	case 1200:
		cfsetispeed(&termOptions, B1200);
		cfsetospeed(&termOptions, B1200);
		break;

	case 600:
		cfsetispeed(&termOptions, B600);
		cfsetospeed(&termOptions, B600);
		break;

	case 300:
        cfsetispeed(&termOptions, B300);
        cfsetospeed(&termOptions, B300);
		break;
	}

	ret = tcsetattr(mFd, TCSANOW, &termOptions);
	if(0 != ret)
	{
		debug_error("tcsetattr()\n");
		return -1;
	}
	return 0;
}

// 停止位 1==1bit, 2==2bit(or 1.5bit)
int TRs232::SetStopbit(int iStopBit)
{
	int ret;
	struct termios termOptions;
	//获取当前的串口配置
	ret = tcgetattr(mFd, &termOptions);
	if(ret != 0)
	{
		debug_error("tcgetattr()\n");
		return -1;
	}

	/* 停止位 1， 2 bit */
	switch (iStopBit)
	{
	default:
	case 1:
		termOptions.c_cflag &= ~CSTOPB;
		break;
	case 2:
		termOptions.c_cflag |= CSTOPB;
		break;
	}

	ret = tcsetattr(mFd, TCSANOW, &termOptions);
	if(0 != ret)
	{
		debug_error("tcsetattr()\n");
		return -1;
	}
	return 0;
}

// 奇偶校验位 0==none, 1==odd奇校验,2==even偶校验;
int TRs232::SetParity(int iParity)
{
	int ret;
	struct termios termOptions;
	//获取当前的串口配置
	ret = tcgetattr(mFd, &termOptions);
	if(ret != 0)
	{
		debug_error("tcgetattr()\n");
		return -1;
	}

	/*设置奇偶校验*/
	switch (iParity)
	{
		default:
		case 0: /*no vertify*/
			termOptions.c_cflag &= ~PARENB;
			termOptions.c_iflag &= ~INPCK;
			break;

		case 1: /*odd vertify*/
			termOptions.c_cflag |= (PARODD | PARENB);
			termOptions.c_iflag |=  INPCK;
			break;

		case 2: /*even vertify*/
			termOptions.c_cflag |=  PARENB;
			termOptions.c_cflag &= ~PARODD;
			termOptions.c_iflag |=  INPCK;
			break;

//		case 'S': /*space vertify*/
//			termOptions.c_cflag &= ~PARENB;
//			termOptions.c_cflag &= ~CSTOPB;
//			termOptions.c_iflag |=  INPCK;
//			break;
	}

	ret = tcsetattr(mFd, TCSANOW, &termOptions);
	if(0 != ret)
	{
		debug_error("tcsetattr()\n");
		return -1;
	}
	return 0;
}

// 数据byte长 8==8bit(默认值),7==7bit,6==6bit,5==5bit;
int TRs232::SetDataBit(int iDataBits)
{
	int ret;
	struct termios termOptions;
	//获取当前的串口配置
	ret = tcgetattr(mFd, &termOptions);
	if(ret != 0)
	{
		debug_error("tcgetattr()\n");
		return -1;
	}

	/*设置串口数据宽度  5,6,7,8bit*/
	termOptions.c_cflag &= ~CSIZE;
	switch (iDataBits)
	{
		case 5:
			termOptions.c_cflag |= CS5;
			break;

		case 6:
			termOptions.c_cflag |= CS6;
			break;

		case 7:
			termOptions.c_cflag |= CS7;
			break;

		case 8:
		default:
			termOptions.c_cflag |= CS8;
			break;
	}

	ret = tcsetattr(mFd, TCSANOW, &termOptions);
	if(0 != ret)
	{
		debug_error("tcsetattr()\n");
		return -1;
	}
	return 0;
}

// 流控 0==none, 1==Xon/Xoff, 2==RTS/CTS;
int TRs232::SetFlowControl(int iFlowControl)
{
	int ret;
	struct termios termOptions;
	//获取当前的串口配置
	ret = tcgetattr(mFd, &termOptions);
	if(ret != 0)
	{
		debug_error("tcgetattr()\n");
		return -1;
	}

	/* 设置控制位: 硬件控制， 软件控制， 无控制  */
	switch (iFlowControl)
	{
	default:
	case 0: /* no data stream control*/
		termOptions.c_cflag &= ~CRTSCTS;
		break;

	case 1: /* software Xon/Xoff  */
		termOptions.c_cflag |=	IXON | IXOFF | IXANY;
		break;

	case 2: /* hardware RTS/CTS */
		termOptions.c_cflag |=  CRTSCTS;
		break;
	}

	ret = tcsetattr(mFd, TCSANOW, &termOptions);
	if(0 != ret)
	{
		debug_error("tcsetattr()\n");
		return -1;
	}
	return 0;
}


int TRs232::SetMode(int iBandrate, int iStopBit, int iParity, int iDataBits, int iFlowControl)
{
	int ret;

	struct termios termOptions;
	//获取当前的串口配置
	ret = tcgetattr(mFd, &termOptions);
	if(ret != 0)
	{
		debug_error("tcgetattr()\n");
		return -1;
	}
	/*flush memory*/
	tcflush(mFd,TCIOFLUSH);

	/*
	// 如果不是开发终端之类的，只是串口传输数据，而不需要串口来处理，
	// 那么使用原始模式(Raw Mode)方式来通讯，设置方式如下：
	*/

	/* 配置local */
	//禁止 (ICANON使用标准输入模式, ECHO显示输入字符)
	termOptions.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG);
	// 本地连接, 可以接收字符
	termOptions.c_cflag |= CLOCAL | CREAD;

	/* 配置输入位 */
	//禁止(INLCR将NL换行转为CR回车 ICRNL将回车转为换行)
	termOptions.c_iflag  &= ~(ICRNL | INLCR);
	termOptions.c_iflag  &= ~(IXON | IXOFF | IXANY);

	/* 配置输出位 */
	//禁止 (OPOST处理后输出)
	termOptions.c_oflag  &= ~OPOST;
	termOptions.c_oflag  &= ~(ONLCR | OCRNL);

 	/* 设置超时等待时间，接收最少字符数 */
	// termOptions.c_cc[VTIME] = 5;  // 0.5秒
	// termOptions.c_cc[VMIN] =  0;

	/*flush memory*/
	tcflush(mFd,TCIOFLUSH);
	ret = tcsetattr(mFd, TCSANOW, &termOptions);
	if(0 != ret)
	{
		debug_error("tcsetattr()\n");
		return -1;
	}

	ret = SetBandrate(iBandrate);     // 设置波特率
	ret = SetStopbit(iStopBit);   // 设置停止位1,2
	ret = SetParity(iParity);     // 设置校验位
	ret = SetDataBit(iDataBits); // 设置数据byte长
	ret = SetFlowControl(iFlowControl);     // 流控
	return ret;
}


// virtual
int TRs232::Open(void *pHandle)
{
	int ret;
    if(NULL == pHandle)
    {
        debug_error("NULL == pHandle \n");
		return -1;
	}

//	mFd = open(mpPath, O_RDWR | O_SYNC	   | O_NOCTTY | O_NDELAY);
//	mFd = open(mpPath, O_RDWR | O_NONBLOCK | O_NOCTTY | O_NDELAY);
//	mFd = open(mpPath, O_RDWR | O_NONBLOCK);
	mFd = open(mpPath, O_RDWR | O_NOCTTY | O_NONBLOCK);   // 非阻塞模式打开
	if(0 > mFd)
	{
         debug_error("open(mpPath) < 0\n");
		return -1;
	}

	// 配置参数
	TRs232Handle *phd = (TRs232Handle *)pHandle;
    ret = SetMode(phd->iBandrate, phd->iStopBit, phd->iParity,
                  phd->iDataBits, phd->iFlowControl);
    if (ret < 0)
	{
         debug_error("ModermSet() < 0\n");
		return -1;
	}
    return  0;
}

// virtual
int TRs232::Close(void *pHandle)
{
	if(mFd != -1)
	{
		close(mFd);
		mFd = -1;
	}
    return 0;
}

/*************************************************************************************//**
*\n 函数名称： TRs232.Read()
*\n 功能描述：
*\n			 读取ps uart1的数据
*\n
*\n 输入参数：
*\n            long address     :  none
*\n            long iSizeToRead : 读取长度
*\n 输出参数:
*\n            void *pBuf       : 数据buffer指针
*\n
*\n 返 回 值:
*\n           n 数据长度; -1 失败; -n 错误码
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2021.5.18     创建
*****************************************************************************************/
// virtual
int TRs232::Read(long address, void *pBuf, long iSizeToRead)
{
	if(mFd < 0)
		return -1;

	int ret = read(mFd, pBuf, iSizeToRead);
	if (ret < 0)
	{
		// debug_error("[%s].read() < 0, %s\n", mName, strerror(errno));
		debug_printf("[%s].read() == 0, %s\n", mName);
		return 0;
	}
	debug_buffer(pBuf, ret);
	return ret;
}


/*************************************************************************************//**
*\n 函数名称： TRs232.Write()
*\n 功能描述：
*\n			 写入ps uart1的数据
*\n
*\n 输入参数：
*\n            long address      :  none
*\n            void *pBuf        : 数据buffer指针
*\n            long iSizeToWrite : 写入长度
*\n 输出参数:
*\n
*\n 返 回 值:
*\n           n 实际写入数据长度; -1 失败; -n 错误码
*\n -----------------------------------------------------------------------------------
*\n  版本:   修改人:       修改日期:        描述:
*\n  V0.01 罗先能        2021.5.18     创建
*****************************************************************************************/
// virtual
int TRs232::Write(long address, void *pBuf, long iSizeToWrite)
{
	if(mFd < 0)
		return -1;

	int ret = write(mFd, pBuf, iSizeToWrite);
	if (ret < 0)
	{
		debug_error("[%s].write() < 0, %s\n", mName, strerror(errno));
		return -1;
	}

	return ret;
}
#endif


